package ldkxingzhe.ldkxingzhedemo.widgets.XZListView;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.Scroller;

/**
 * 支持下拉刷新, 上拉加载更多的listview
 * 大部分源码来自于XListView, 感谢作者.
 * Created by xingzhe on 15/11/13.
 */
public class XZListView extends ListView implements AbsListView.OnScrollListener{
    private final String TAG = XZListView.class.getSimpleName();

    // MARK: 构造函数部分
    public XZListView(Context context) {
        this(context, null);
    }
    public XZListView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public XZListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initView();
    }


    private Scroller mScroller;
    private Context mContext;
    private XZHeaderView mHeaderView;
    private int mHeaderViewHeight;
    private int mRefreshTime = 1000;
    private float mLastY = -1;
    private final float OFFSET_RADIO = 1.5f;
    // 初始化
    private void initView() {
        mScroller = new Scroller(mContext, new DecelerateInterpolator());
        mHeaderView = new XZHeaderView(mContext);

        mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Log.v(TAG,"onGlobalLayout");
                mHeaderViewHeight = mHeaderView.mContainerContent.getHeight();
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
        addHeaderView(mHeaderView);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if(mLastY == -1){
            mLastY = ev.getRawY();
        }

        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                mLastY = ev.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                float tmpRawY = ev.getRawY();
                final float deltaY = tmpRawY - mLastY;
                mLastY = tmpRawY;
                if(getFirstVisiblePosition() == 0 && (mHeaderView.getVisibleHeight() > 0 || deltaY > 0)){
                    updateHeaderViewHeight(deltaY/OFFSET_RADIO);
                }
                break;
            default:
                mLastY = -1;
                if(getFirstVisiblePosition() == 0 && mHeaderView.getVisibleHeight() > mHeaderViewHeight){
                    mHeaderView.setState(XZListViewState.REFRESHING);
                    Log.v(TAG,"refreshing");
                }
                resetHeaderHeight();
        }
        return super.onTouchEvent(ev);
    }

    private void resetHeaderHeight() {
        int height = mHeaderView.getVisibleHeight();
        if(height == 0){return;}
        int finalHeight = 0;
        if(height > mHeaderViewHeight){
            finalHeight = mHeaderViewHeight;
        }
        mScroller.startScroll(0, height, 0, finalHeight - height, mRefreshTime);
        invalidate();
    }

    private void updateHeaderViewHeight(float v) {
        mHeaderView.setVisibleHeight((int) (v + mHeaderView.getVisibleHeight()));

        if(mHeaderView.getVisibleHeight() > mHeaderViewHeight){
            mHeaderView.setState(XZListViewState.READY);
        }else{
            mHeaderView.setState(XZListViewState.PULLING);
        }
    }

    @Override
    public void computeScroll() {
        if(mScroller.computeScrollOffset()){
            mHeaderView.setVisibleHeight(mScroller.getCurrY());
        }
        postInvalidate();
        super.computeScroll();
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }
}

enum XZListViewState{
    NORMAL,  //正常状态
    PULLING,  // 开始下拉, 并未到达刷新临界点
    READY,    // 下拉达到临界点, 松手后开始刷新
    REFRESHING // 刷新ing
}
